import React from 'react';
import L from 'leaflet';
import {
  Marker, Popup, Tooltip, FeatureGroup, withLeaflet
} from 'react-leaflet';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import { isEqual, isEmpty } from 'lodash';
import { isLngLat } from 'src/util/mapUtil';
import setting from './setting';
import './index.less';
import defaultImageIcon from './image/flag.png';

class LMarker5 extends React.Component {
  static setting = setting;

  constructor(props) {
    super(props);
    const { fields } = props.events.click;
    const id = fields.id.value === undefined ? '' : fields.id.value;
    const lng = fields.lng.value === undefined ? '' : fields.lng.value;
    const lat = fields.lat.value === undefined ? '' : fields.lat.value;
    this.setDataPool({ id, lng, lat });
  }

  componentWillReceiveProps(nextProps) {
    const {
      data, events, leaflet: { map }
    } = this.props;
    const {
      data: nextData, events: nextEvents
    } = nextProps;
    const { toFit, boundaryMargin } = this.default;

    // 按照marker数据适配地图视图
    if (!isEqual(data, nextData) && toFit && nextData.length) {
      const list = nextData.filter(({ lng, lat }) => isLngLat(lng, lat))
        .map(item => [item.lat, item.lng]);
      if (list.length > 1) {
        map.fitBounds(
          list, { padding: [boundaryMargin, boundaryMargin] }
        );
      }
    }
    if (!isEqual(data, nextData) || !isEqual(nextEvents.click, events.click)) {
      if (nextData && nextData[0] && nextEvents.click.action.active) {
        const { lng, lat, id } = nextData[0];
        this.setDataPool({ lng, lat, id });
        this.updateEventsDefaultValue({ lng, lat, id });
      }
    }
  }


  // 默认设置
  get default() {
    const {
      config: {
        default: {
          content, position, minSize, maxSize, boundaryMargin, toFit
        }
      }
    } = this.props;
    return {
      position, minSize, maxSize, ...content, boundaryMargin, toFit
    };
  }

  // 聚合设置
  get cluster() {
    const { config: { cluster } } = this.props;
    return cluster;
  }

  // 提示框设置
  get tooltip() {
    const { config: { tooltip } } = this.props;

    return tooltip;
  }

  // 弹窗设置
  get popup() {
    const { config: { popup } } = this.props;
    return popup;
  }

  // 动作设置
  get action() {
    const { config: { action: { detail } } } = this.props;
    return detail;
  }

  // 获得经纬度点位数组的value边界
  get valueBound() {
    const { data } = this.props;
    const values = data.map(item => item.value || 1);
    return {
      valueMax: Math.max(...values),
      valueMin: Math.min(...values)
    };
  }

  // 获得点位大小
  getIconSize = (value) => {
    const { maxSize, minSize } = this.default;

    const { valueMax, valueMin } = this.valueBound;
    if (valueMax === valueMin) return (maxSize + minSize) / 2;

    return Math.floor((maxSize - minSize) * (value - valueMin)
      / (valueMax - valueMin) + minSize);
  };

  // 获得图片icon
  getImageIcon = (value, id) => {
    const { imageUrl, position } = this.default;

    const size = this.getIconSize(value);
    const iconAnchor = position === 'center'
      ? [size / 2, size / 2] : [size / 2, size];
    return L.divIcon({
      className: 'noBackground',
      html: `<img id="${id}" width="${size}" src="${imageUrl || defaultImageIcon}" />`,
      iconSize: [size, size],
      iconAnchor
    });
    // return L.icon({
    //   className: `${isSelectionIcon ? 'marker-beat' : ''}`,
    //   iconUrl: imageUrl || defaultImageIcon,
    //   iconSize: [size, size],
    //   iconAnchor, // 图标中心点
    // });
  };

  // 获得散点icon
  getSpotIcon = (value, id) => {
    const { shape, position } = this.default;
    const size = this.getIconSize(value);
    const color = this.getSpotColor(value);

    return L.divIcon({
      className: 'noBackground',
      html: `<div id="${id}" style="font-size: ${size}px; color: ${color}" class="monetfont icon-${shape}" />`,
      iconSize: [size, size],
      iconAnchor: position === 'center' ? [size / 2, size / 2]
        : [size / 2, size]
    });
  };

  // 获得散点颜色
  getSpotColor = (value) => {
    const { colors } = this.default;
    const set = colors.reduce((pre, item) =>
      (item.start < value && value <= item.end ? item.color : pre), null);
    return set || colors[0].color;
  };

  // 提示框样式
  getTooltipStyle = () => {
    const {
      font, borderColor, borderWidth,
      background: { type, backgroundColor, imageUrl },
      size: { constant, width, height }
    } = this.tooltip;
    const myBackground = type === 'color' ? { backgroundColor } : { backgroundImage: `url(${imageUrl})` };

    return {
      border: `${borderWidth}px solid ${borderColor}`,
      ...myBackground,
      ...font,
      width: constant ? width : 'auto',
      height: constant ? height : 'auto',
      position: 'relative'
    };
  };

  // 提示框内容样式
  getTooltipInnerStyle = () => {
    const {
      size: { constant }, position: { align, top }
    } = this.tooltip;

    return {
      width: constant ? '100%' : 'auto',
      textAlign: align,
      display: 'block',
      position: constant ? 'absolute' : 'stastic',
      top
    };
  };

  // 弹窗样式
  getPopupStyle = () => {
    const {
      backgroundColor, borderColor, borderWidth,
      width, height
    } = this.popup;

    return {
      border: `${borderWidth}px solid ${borderColor}`,
      backgroundColor,
      width,
      height
    };
  };

  // 聚合点大小
  computeClusterSize = (count) => {
    const { clusterSize } = this.cluster;
    const degree = [10, 50, 100, 200, 500, 1000, 10000, 100000];
    const diff = 5;

    return degree.reduce((pre, cur) => {
      if (count >= cur) {
        return pre + diff;
      }
      return pre;
    }, clusterSize);
  }

  // 获得聚合点
  getClusterIcon = (cluster) => {
    const { backgroundImage, font } = this.cluster;

    const count = cluster.getChildCount();
    const size = this.computeClusterSize(count);
    const background = backgroundImage
      ? [`background-image: url(${backgroundImage})`, 'background-size:cover']
      : ['border:3px solid #D7BC2F',
        'border-radius:50%',
        'background: rgba(215,188,47,0.6)'];

    const style = [
      ...background,
      `font-family:${font.fontFamily}`,
      `color:${font.color}`,
      `font-weight:${font.fontWeight}`,
      `font-size:${font.fontSize}px`,
    ];
    return L.divIcon({
      html: `<span class="marker-cluster-main" style="${style.join(';')}" >${count}</span>`,
      className: 'marker-cluster-custom',
      iconSize: L.point(size, size, true),
    });
  }

  // 获得图标或散点
  getIconMarker = (data) => {
    const {
      lng, lat, value, id
    } = data;
    const opsValue = value || 1;
    const { type } = this.default;
    const spotIcon = this.getSpotIcon(opsValue, id);
    const imageIcon = this.getImageIcon(opsValue, id);

    return (<Marker
      position={[lat, lng]}
      icon={type === 'spot' ? spotIcon : imageIcon}
    />);
  };

  // 获得提示框文本
  getTooltipContext = (text) => {
    const infoArray = `${text}`.split(';');
    return (<section
      className="map-marker-content"
      style={this.getTooltipStyle()}
    >
      {infoArray.map((item, idx) =>
        (<React.Fragment key={`line${idx}`}>
          <span style={this.getTooltipInnerStyle()}>
            {item}
            <br />
          </span>
        </React.Fragment>))
      }
    </section>);
  };

  // 获得视频弹出框
  getPopupContext = (url) => (<iframe
    src={url}
    title={url}
    style={this.getPopupStyle()}
  >
  </iframe>);

  // 获得交互事件和弹窗
  renderMarker = (data) => {
    const {
      lng, lat, link, tooltip, value, id, iframe
    } = data;
    const opsValue = value || 1;
    const { show } = this.tooltip;
    const { type } = this.default;
    const spotIcon = this.getSpotIcon(opsValue, id);
    const imageIcon = this.getImageIcon(opsValue, id);
    return (<Marker
      position={[lat, lng]}
      icon={type === 'spot' ? spotIcon : imageIcon}
      onClick={() => this.onClickMarker(lng, lat, link, id)}
    >
      {(tooltip && show === 'click')
        && <Popup
          position={[lat, lng]}
          className="marker-popup"
          closeButton={false}
          autoPanPaddingTopLeft={[0, -10]}
        >
          {this.getTooltipContext(tooltip)}
        </Popup>}

      {(iframe && this.action.type === 'popup')
      && <Popup
        position={[lat, lng]}
        className="marker-popup"
        maxWidth={800}
      >
        {this.getPopupContext(iframe)}
      </Popup>}

      {tooltip && (show === 'always' || show === 'hover')
        && <Tooltip
          direction="top"
          key={Math.floor(Math.random() * 1000)}
          permanent={show === 'always'}
          className="marker-tooltip"
          offset={[0, -10]}
        >
          {this.getTooltipContext(tooltip)}
        </Tooltip>}
    </Marker>);
  };

  onClickMarker = (lng, lat, link, id) => {
    const { type, target } = this.action;
    if (link && type === 'link') {
      switch (target) {
        case 'forward':
          window.location.href = link;
          break;
        case 'newTab':
          window.open(link);
          break;
        default: break;
      }
    }

    // 交互功能
    const { events: { click } } = this.props;
    if (click.action.active) {
      this.setDataPool({ lng, lat, id });
    }
    // 点击选中或者取消选中
    const lastActiveMarkers = document.getElementsByClassName('marker-beat');
    for (let i = 0; i < lastActiveMarkers.length; i++) {
      lastActiveMarkers[i].classList.remove('marker-beat');
    }

    const currentMarker = document.getElementById(id);
    currentMarker.classList.add('marker-beat');
  };

  // 更新store中的dataPoll
  setDataPool(dataPoll) {
    const {
      bigScreen: { setDataPool }, editable,
      events: { click },
      path
    } = this.props;
    setDataPool(click, dataPoll, path, editable);
  }

  // 更新交互事件绑定的默认值
  updateEventsDefaultValue(dataPoll) {
    const {
      bigScreen: { updateEventsDefaultValue }, path, editable
    } = this.props;
    if (!editable) return;
    const eventValues = Object.keys(dataPoll).reduce(
      (pre, key) => Object.assign(pre,
        { [`click.fields.${key}.value`]: dataPoll[key] }), {}
    );
    updateEventsDefaultValue(path, eventValues);
  }

  getMarkers(data) {
    return data.filter(({ lng, lat }) => isLngLat(lng, lat))
      .map((item, index) =>
        (<FeatureGroup key={`group${index}`}>
          {this.renderMarker(item)}
        </FeatureGroup>));
  }

  render() {
    const { useCluster, clusterRadius, showCoverage } = this.cluster;
    const { data } = this.props;

    if (isEmpty(data)) return null;
    const markers = this.getMarkers(data);

    return (
      <React.Fragment>
        {useCluster ? <MarkerClusterGroup
          maxClusterRadius={clusterRadius}
          iconCreateFunction={this.getClusterIcon}
          showCoverageOnHover={showCoverage}
        >
          {markers}
        </MarkerClusterGroup>
          : markers}
      </React.Fragment>
    );
  }
}

export default withLeaflet(LMarker5);
